use rand::Rng;
use jni::JNIEnv;
use jni::objects::{JClass, JString};
use jni::sys::jint;
use std::{env, string};


#[macro_use]
extern crate log;

#[cfg(target_os = "android")]
extern crate android_logger;

use log::LevelFilter;
#[cfg(target_os = "android")]
use android_logger::{Config,FilterBuilder};

#[cfg(target_os = "android")]
fn init_android_logger() {
    android_logger::init_once(
        Config::default()
            .with_max_level(LevelFilter::Trace) // limit log level
            .with_tag("rust_lib_demo") // logs will show under mytag tag
    );

    // debug!("this is a debug {}", "message");
    // error!("this is printed by default");
}

#[cfg(not(target_os = "android"))]
fn init_android_logger(){}

#[no_mangle]
pub extern "system" fn Java_com_korion_learn_andriod_1rust_JNIBridge_gen_1random_1num<'local>(mut env: JNIEnv<'local>, clazz: JClass<'local>) -> jint {
    init_android_logger();
    let number = generate_random_number();
    debug!("generate random number: {}", number);
    return number as jint;
}

#[no_mangle]
pub extern "system" fn Java_com_korion_learn_andriod_1rust_JNIBridge_dump_1coverage<'local>(mut env: JNIEnv<'local>, clazz: JClass<'local>, j_path: JString<'local>) {
    let path: String = env.get_string(&j_path).expect("Couldn't get java string").into();
    c_capture_coverage(&path);
}

#[no_mangle]
pub extern "C" fn c_generate_random_number() -> u32 {
    return generate_random_number();
}



pub fn generate_random_number() -> u32 {
    for (key, value) in env::vars() {
        println!("{}: {}", key, value);
        debug!("{}: {}", key, value);
    }
    let mut rng = rand::thread_rng();
    return rng.gen_range(0..1000);
}

#[no_mangle]
pub extern "C" fn c_capture_coverage(path: &String) {
    debug!("capture_coverage: start {}", path);
    let mut coverage = vec![];
    unsafe {
        // Note that this function is not thread-safe! Use a lock if needed.
        minicov::capture_coverage(&mut coverage).unwrap();
    }
    std::fs::write(path, coverage).unwrap();
    debug!("capture_coverage: write to {}", path);
}
